系統中可以自訂標籤 (Tags),而且每個標籤還可以上傳專屬的 Icon。在 React 中上傳檔案給後端,我們不能像前面幾天一樣直接把檔案塞進 {} 裡面當 JSON 送出,我們必須透過瀏覽器原生的 FormData 物件來幫忙打包!
application/json vs multipart/form-data為什麼上傳檔案這麼特別,要換另一種格式?
| 傳輸格式 | 特性 | 適用情境 |
|---|---|---|
application/json |
以純文字 (字串) 的方式傳輸,結構清晰,幾乎是現代 API 的標準。 | 傳送帳號、密碼、寶可夢備註等一般文字資料。 |
multipart/form-data |
能夠將請求切割成「多個片段 (Parts)」,每個片段之間用一條 Boundary 分界線隔開。它允許您同時把一段二進位圖片 (二進制碼) 混合著普通文字一起傳輸! |
遇到要傳送圖片、影片、PDF 等實體檔案時的唯一解。 |
假設我們已經用 <input type="file" /> 拿到了一個檔案物件 selectedFile,上傳的實作邏輯如下:
import api from '../api/client';
const uploadTagIcon = async (tagId: number, selectedFile: File) => {
// 1. 建立 FormData 物件
const formData = new FormData();
// 2. 將檔案加入表單 (名稱必須與後端 Multer 寫的 upload.single('icon') 一致!)
formData.append('icon', selectedFile);
try {
// 3. 發送 POST 請求
// 注意:Axios 非常聰明,只要偵測到您傳入的是 FormData 物件,
// 就會自動把 Headers 的 Content-Type 改為 multipart/form-data,不需手動設定!
const response = await api.post(`/tags/${tagId}/icon`, formData);
console.log("上傳成功!", response.data);
alert('標籤圖示更新成功!');
} catch (error) {
console.error("上傳失敗", error);
}
};
在前端上傳檔案其實就是這麼簡單:建立 FormData -> 把檔案 append 進去 -> 丟給 Axios。這就是前後端協作完美的典範!

系統管理介面中,選擇標籤定義管理,可以看到所有已定義好的標籤。

這些標籤可自行編輯,包含選擇圖片更新標籤Icon。
透過 FormData 的助攻,我們完美打通了前後端的圖示上傳功能,並在後端轉成 Base64 永久儲存。階段三的「React 前端實作」到此告一段落!明天起,我們要進入進階的效能優化篇章。